package com.handu.luna.core.domain.user;

import javax.persistence.Entity;
import javax.persistence.Transient;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;
import org.springframework.data.jpa.domain.Specification;

import com.handu.luna.core.domain.BasePersistentDomain;

import java.sql.Timestamp;
import java.time.ZonedDateTime;
import java.util.List;

@Entity
public class User extends BasePersistentDomain<UserRepository> {

	public static final int MaxInvalidPasswordTryCount = 5;
	public static final long FrozenMinutes = 30l;

	public User() {
		this.name = "客人";

	};

	public User(String name, String password, String email, String userSex,
			String mobile, String isMobileCheck, String isEmailCheck,
			int levelPoint, int consumePoint, UserStatus status) {
		super();
		this.name = name;
		this.password = password;
		this.email = email;
		this.userSex = userSex;
		this.mobile = mobile;
		this.isMobileCheck = isMobileCheck;
		this.isEmailCheck = isEmailCheck;
		this.levelPoint = levelPoint;
		this.consumePoint = consumePoint;
		this.status = status;
	}

	public enum UserStatus {
		NORMAL("启用"), LOCKED("锁定");
		public String description;

		UserStatus(final String description) {
			this.description = description;
		}

	}

	@Size(min = 1, max = 50, message = "用户名长度不能为空或超过50个字符。")
	private String name;
	private String password;
	@Size(min = 1, message = "邮箱不能为空")
	@Email(message = "email地址无效！")
	private String email;
	private String userRank;
	private String userSex;
	@Size(min = 1, max = 11, message = "手机号不能为空")
	private String mobile;
	private String userBirthday;
	private String isMobileCheck;
	private String isEmailCheck;
	private int levelPoint;
	private int consumePoint;
	private String passwordSalt;
	private String tokenSalt;// 是否选中登录表示
	private String ValidataCode;
	private Timestamp RegisterDate;

	@Transient
	private long userRankId;// 用户等级ID
	@Transient
	private long goodsSale;// 商品折扣
	@Transient
	private String rankName;// 用户名称
	
	@Transient
	private String atuLogin;// 自动登录

	public String getAtuLogin() {
		return atuLogin;
	}

	public void setAtuLogin(String atuLogin) {
		this.atuLogin = atuLogin;
	}

	public long getUserRankId() {
		return userRankId;
	}

	public void setUserRankId(long userRankId) {
		this.userRankId = userRankId;
	}

	public long getGoodsSale() {
		return goodsSale;
	}

	public void setGoodsSale(long goodsSale) {
		this.goodsSale = goodsSale;
	}

	public String getRankName() {
		return rankName;
	}

	public void setRankName(String rankName) {
		this.rankName = rankName;
	}

	public String getValidataCode() {
		return ValidataCode;
	}

	public void setValidataCode(String validataCode) {
		ValidataCode = validataCode;
	}

	public Timestamp getRegisterDate() {
		return RegisterDate;
	}

	public void setRegisterDate(Timestamp registerDate) {
		RegisterDate = registerDate;
	}

	public String getPasswordSalt() {
		return passwordSalt;
	}

	public void setPasswordSalt(String passwordSalt) {
		this.passwordSalt = passwordSalt;
	}

	public String getTokenSalt() {
		return tokenSalt;
	}

	public void setTokenSalt(String tokenSalt) {
		this.tokenSalt = tokenSalt;
	}

	public String getIsMobileCheck() {
		return isMobileCheck;
	}

	public void setIsMobileCheck(String isMobileCheck) {
		this.isMobileCheck = isMobileCheck;
	}

	public String getIsEmailCheck() {
		return isEmailCheck;
	}

	public void setIsEmailCheck(String isEmailCheck) {
		this.isEmailCheck = isEmailCheck;
	}

	public int getLevelPoint() {
		return levelPoint;
	}

	public void setLevelPoint(int levelPoint) {
		this.levelPoint = levelPoint;
	}

	public int getConsumePoint() {
		return consumePoint;
	}

	public void setConsumePoint(int consumePoint) {
		this.consumePoint = consumePoint;
	}

	public String getUserRank() {
		return userRank;
	}

	public void setUserRank(String userRank) {
		this.userRank = userRank;
	}

	public String getUserSex() {
		return userSex;
	}

	public void setUserSex(String userSex) {
		this.userSex = userSex;
	}

	public String getUserBirthday() {
		return userBirthday;
	}

	public void setUserBirthday(String userBirthday) {
		this.userBirthday = userBirthday;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	private UserStatus status;
	private int invalidPasswordTryCount;// 错误密码的次数
	private ZonedDateTime lastInvalidPasswordTime;// 错误密码的最后登陆时间

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public UserStatus getStatus() {
		return status;
	}

	public void setStatus(UserStatus status) {
		this.status = status;
	}

	public int getInvalidPasswordTryCount() {
		return invalidPasswordTryCount;
	}

	public void setInvalidPasswordTryCount(int invalidPasswordTryCount) {
		this.invalidPasswordTryCount = invalidPasswordTryCount;
	}

	public ZonedDateTime getLastInvalidPasswordTime() {
		return lastInvalidPasswordTime;
	}

	public void setLastInvalidPasswordTime(ZonedDateTime lastInvalidPasswordTime) {
		this.lastInvalidPasswordTime = lastInvalidPasswordTime;
	}

	public void initUserRank(User user){
		int i = user.getLevelPoint();
		List<UserRank> userRankList = context.getUserRankRepository().findAll();
				for (int j = 0; j < userRankList.size(); j++) {
					if(userRankList.get(j).getMaxRank() >i && i>userRankList.get(j).getMinRank()){
						user.setUserRankId(userRankList.get(j).getId());
						user.setGoodsSale(userRankList.get(j).getGoodsSale());
						user.setRankName(userRankList.get(j).getRankName());
					}
				}
	}

	public User login() {
		checkInvalidNameOrPasswordCount();

		List<User> result = context.getUserRepository().findByNameAndPassword(
				this.name, this.password);
		if (result.isEmpty()) {
			List<User> resultUser = context.getUserRepository().findByName(
					this.name);
			if (resultUser.isEmpty()) {
				throw new InvalidNameOrPasswordException();
			}
			User user = resultUser.get(0);
			user.invalidPasswordTryCount++;
			user.lastInvalidPasswordTime = ZonedDateTime.now();
			context.getUserRepository().save(user);
			throw new InvalidNameOrPasswordException();
		} else {
			User user = result.get(0);
			if (user.status == UserStatus.LOCKED) {
				throw new InvalidNameOrPasswordException();
			}
			return user;
		}
	}

	public void checkInvalidNameOrPasswordCount() {
		List<User> userListWithSameName = context.getUserRepository()
				.findByName(this.name);
		if (userListWithSameName.isEmpty()) {
			throw new InvalidNameOrPasswordException();
		} else {
			User user = userListWithSameName.get(0);
			if (user.invalidPasswordTryCount >= MaxInvalidPasswordTryCount) {
				if (user.lastInvalidPasswordTime != null) {
					if (user.lastInvalidPasswordTime.plusMinutes(FrozenMinutes)
							.isAfter(ZonedDateTime.now())) {
						throw new UserFrozenException();
					} else {
						user.invalidPasswordTryCount = 0;
						user.lastInvalidPasswordTime = null;
						context.getUserRepository().save(user);
					}
				}
			}
		}
	}

	@Override
	public String toString() {
		return String.format("User[id=%d, name='%s', status='%s']", id, name,
				status);
	}

	public static Specification<User> nameLike(String searchWord) {
		return new Specification<User>() {
			@Override
			public Predicate toPredicate(Root<User> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {
				if (searchWord != null) {
					query.where(builder.like(root.get("name").as(String.class),
							"%" + searchWord + "%"));
				}
				return query.getRestriction();
			}
		};
	}
}
